1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.google.common.base;
18
19 import static com.google.common.testing.SerializableTester.reserialize;
20
21 import com.google.common.annotations.GwtCompatible;
22 import com.google.common.annotations.GwtIncompatible;
23 import com.google.common.collect.Lists;
24 import com.google.common.testing.ClassSanityTester;
25 import com.google.common.testing.EqualsTester;
26
27 import junit.framework.TestCase;
28
29 import java.io.Serializable;
30 import java.util.ArrayList;
31 import java.util.List;
32 import java.util.concurrent.TimeUnit;
33 import java.util.concurrent.TimeoutException;
34 import java.util.concurrent.atomic.AtomicInteger;
35 import java.util.concurrent.atomic.AtomicReference;
36
37
38
39
40
41
42
43 @GwtCompatible(emulated = true)
44 public class SuppliersTest extends TestCase {
45 public void testCompose() {
46 Supplier<Integer> fiveSupplier = new Supplier<Integer>() {
47 @Override
48 public Integer get() {
49 return 5;
50 }
51 };
52
53 Function<Number, Integer> intValueFunction =
54 new Function<Number, Integer>() {
55 @Override
56 public Integer apply(Number x) {
57 return x.intValue();
58 }
59 };
60
61 Supplier<Integer> squareSupplier = Suppliers.compose(intValueFunction,
62 fiveSupplier);
63
64 assertEquals(Integer.valueOf(5), squareSupplier.get());
65 }
66
67 public void testComposeWithLists() {
68 Supplier<ArrayList<Integer>> listSupplier
69 = new Supplier<ArrayList<Integer>>() {
70 @Override
71 public ArrayList<Integer> get() {
72 return Lists.newArrayList(0);
73 }
74 };
75
76 Function<List<Integer>, List<Integer>> addElementFunction =
77 new Function<List<Integer>, List<Integer>>() {
78 @Override
79 public List<Integer> apply(List<Integer> list) {
80 ArrayList<Integer> result = Lists.newArrayList(list);
81 result.add(1);
82 return result;
83 }
84 };
85
86 Supplier<List<Integer>> addSupplier = Suppliers.compose(addElementFunction,
87 listSupplier);
88
89 List<Integer> result = addSupplier.get();
90 assertEquals(Integer.valueOf(0), result.get(0));
91 assertEquals(Integer.valueOf(1), result.get(1));
92 }
93
94 static class CountingSupplier implements Supplier<Integer>, Serializable {
95 private static final long serialVersionUID = 0L;
96 transient int calls = 0;
97 @Override
98 public Integer get() {
99 calls++;
100 return calls * 10;
101 }
102 }
103
104 public void testMemoize() {
105 CountingSupplier countingSupplier = new CountingSupplier();
106 Supplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
107 checkMemoize(countingSupplier, memoizedSupplier);
108 }
109
110 public void testMemoize_redudantly() {
111 CountingSupplier countingSupplier = new CountingSupplier();
112 Supplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
113 assertSame(memoizedSupplier, Suppliers.memoize(memoizedSupplier));
114 }
115
116 @GwtIncompatible("SerializableTester")
117 public void testMemoizeSerialized() {
118 CountingSupplier countingSupplier = new CountingSupplier();
119 Supplier<Integer> memoizedSupplier = Suppliers.memoize(countingSupplier);
120 checkMemoize(countingSupplier, memoizedSupplier);
121
122 memoizedSupplier.get();
123
124 Supplier<Integer> copy = reserialize(memoizedSupplier);
125 memoizedSupplier.get();
126
127 CountingSupplier countingCopy = (CountingSupplier)
128 ((Suppliers.MemoizingSupplier<Integer>) copy).delegate;
129 checkMemoize(countingCopy, copy);
130 }
131
132 private void checkMemoize(
133 CountingSupplier countingSupplier, Supplier<Integer> memoizedSupplier) {
134
135 assertEquals(0, countingSupplier.calls);
136
137 assertEquals(10, (int) memoizedSupplier.get());
138
139
140 assertEquals(1, countingSupplier.calls);
141
142 assertEquals(10, (int) memoizedSupplier.get());
143
144
145 assertEquals(1, countingSupplier.calls);
146 }
147
148 public void testMemoizeExceptionThrown() {
149 Supplier<Integer> exceptingSupplier = new Supplier<Integer>() {
150 @Override
151 public Integer get() {
152 throw new NullPointerException();
153 }
154 };
155
156 Supplier<Integer> memoizedSupplier = Suppliers.memoize(exceptingSupplier);
157
158
159
160 for (int i = 0; i < 2; i++) {
161 try {
162 memoizedSupplier.get();
163 fail("failed to throw NullPointerException");
164 } catch (NullPointerException e) {
165
166 }
167 }
168 }
169
170 @GwtIncompatible("Thread.sleep")
171 public void testMemoizeWithExpiration() throws InterruptedException {
172 CountingSupplier countingSupplier = new CountingSupplier();
173
174 Supplier<Integer> memoizedSupplier = Suppliers.memoizeWithExpiration(
175 countingSupplier, 75, TimeUnit.MILLISECONDS);
176
177 checkExpiration(countingSupplier, memoizedSupplier);
178 }
179
180 @GwtIncompatible("Thread.sleep, SerializationTester")
181 public void testMemoizeWithExpirationSerialized()
182 throws InterruptedException {
183 CountingSupplier countingSupplier = new CountingSupplier();
184
185 Supplier<Integer> memoizedSupplier = Suppliers.memoizeWithExpiration(
186 countingSupplier, 75, TimeUnit.MILLISECONDS);
187
188 memoizedSupplier.get();
189
190 Supplier<Integer> copy = reserialize(memoizedSupplier);
191 memoizedSupplier.get();
192
193 CountingSupplier countingCopy = (CountingSupplier)
194 ((Suppliers.ExpiringMemoizingSupplier<Integer>) copy).delegate;
195 checkExpiration(countingCopy, copy);
196 }
197
198 @GwtIncompatible("Thread.sleep")
199 private void checkExpiration(
200 CountingSupplier countingSupplier, Supplier<Integer> memoizedSupplier)
201 throws InterruptedException {
202
203 assertEquals(0, countingSupplier.calls);
204
205 assertEquals(10, (int) memoizedSupplier.get());
206
207 assertEquals(1, countingSupplier.calls);
208
209 assertEquals(10, (int) memoizedSupplier.get());
210
211 assertEquals(1, countingSupplier.calls);
212
213 Thread.sleep(150);
214
215 assertEquals(20, (int) memoizedSupplier.get());
216
217 assertEquals(2, countingSupplier.calls);
218
219 assertEquals(20, (int) memoizedSupplier.get());
220
221 assertEquals(2, countingSupplier.calls);
222 }
223
224 public void testOfInstanceSuppliesSameInstance() {
225 Object toBeSupplied = new Object();
226 Supplier<Object> objectSupplier = Suppliers.ofInstance(toBeSupplied);
227 assertSame(toBeSupplied,objectSupplier.get());
228 assertSame(toBeSupplied,objectSupplier.get());
229 }
230
231 public void testOfInstanceSuppliesNull() {
232 Supplier<Integer> nullSupplier = Suppliers.ofInstance(null);
233 assertNull(nullSupplier.get());
234 }
235
236 @GwtIncompatible("Thread")
237
238 public void testExpiringMemoizedSupplierThreadSafe() throws Throwable {
239 Function<Supplier<Boolean>, Supplier<Boolean>> memoizer =
240 new Function<Supplier<Boolean>, Supplier<Boolean>>() {
241 @Override public Supplier<Boolean> apply(Supplier<Boolean> supplier) {
242 return Suppliers.memoizeWithExpiration(
243 supplier, Long.MAX_VALUE, TimeUnit.NANOSECONDS);
244 }
245 };
246 testSupplierThreadSafe(memoizer);
247 }
248
249 @GwtIncompatible("Thread")
250
251 public void testMemoizedSupplierThreadSafe() throws Throwable {
252 Function<Supplier<Boolean>, Supplier<Boolean>> memoizer =
253 new Function<Supplier<Boolean>, Supplier<Boolean>>() {
254 @Override public Supplier<Boolean> apply(Supplier<Boolean> supplier) {
255 return Suppliers.memoize(supplier);
256 }
257 };
258 testSupplierThreadSafe(memoizer);
259 }
260
261 @GwtIncompatible("Thread")
262 public void testSupplierThreadSafe(
263 Function<Supplier<Boolean>, Supplier<Boolean>> memoizer)
264 throws Throwable {
265 final AtomicInteger count = new AtomicInteger(0);
266 final AtomicReference<Throwable> thrown =
267 new AtomicReference<Throwable>(null);
268 final int numThreads = 3;
269 final Thread[] threads = new Thread[numThreads];
270 final long timeout = TimeUnit.SECONDS.toNanos(60);
271
272 final Supplier<Boolean> supplier = new Supplier<Boolean>() {
273 boolean isWaiting(Thread thread) {
274 switch (thread.getState()) {
275 case BLOCKED:
276 case WAITING:
277 case TIMED_WAITING:
278 return true;
279 default:
280 return false;
281 }
282 }
283
284 int waitingThreads() {
285 int waitingThreads = 0;
286 for (Thread thread : threads) {
287 if (isWaiting(thread)) {
288 waitingThreads++;
289 }
290 }
291 return waitingThreads;
292 }
293
294 @Override
295 public Boolean get() {
296
297
298 long t0 = System.nanoTime();
299 while (waitingThreads() != numThreads - 1) {
300 if (System.nanoTime() - t0 > timeout) {
301 thrown.set(new TimeoutException(
302 "timed out waiting for other threads to block" +
303 " synchronizing on supplier"));
304 break;
305 }
306 Thread.yield();
307 }
308 count.getAndIncrement();
309 return Boolean.TRUE;
310 }
311 };
312
313 final Supplier<Boolean> memoizedSupplier = memoizer.apply(supplier);
314
315 for (int i = 0; i < numThreads; i++) {
316 threads[i] = new Thread() {
317 @Override public void run() {
318 assertSame(Boolean.TRUE, memoizedSupplier.get());
319 }
320 };
321 }
322 for (Thread t : threads) {
323 t.start();
324 }
325 for (Thread t : threads) {
326 t.join();
327 }
328
329 if (thrown.get() != null) {
330 throw thrown.get();
331 }
332 assertEquals(1, count.get());
333 }
334
335 @GwtIncompatible("Thread")
336
337 public void testSynchronizedSupplierThreadSafe()
338 throws InterruptedException {
339 final Supplier<Integer> nonThreadSafe = new Supplier<Integer>() {
340 int counter = 0;
341 @Override
342 public Integer get() {
343 int nextValue = counter + 1;
344 Thread.yield();
345 counter = nextValue;
346 return counter;
347 }
348 };
349
350 final int numThreads = 10;
351 final int iterations = 1000;
352 Thread[] threads = new Thread[numThreads];
353 for (int i = 0; i < numThreads; i++) {
354 threads[i] = new Thread() {
355 @Override public void run() {
356 for (int j = 0; j < iterations; j++) {
357 Suppliers.synchronizedSupplier(nonThreadSafe).get();
358 }
359 }
360 };
361 }
362 for (Thread t : threads) {
363 t.start();
364 }
365 for (Thread t : threads) {
366 t.join();
367 }
368
369 assertEquals(numThreads * iterations + 1, (int) nonThreadSafe.get());
370 }
371
372 public void testSupplierFunction() {
373 Supplier<Integer> supplier = Suppliers.ofInstance(14);
374 Function<Supplier<Integer>, Integer> supplierFunction =
375 Suppliers.supplierFunction();
376
377 assertEquals(14, (int) supplierFunction.apply(supplier));
378 }
379
380 @GwtIncompatible("SerializationTester")
381 public void testSerialization() {
382 assertEquals(
383 Integer.valueOf(5), reserialize(Suppliers.ofInstance(5)).get());
384 assertEquals(Integer.valueOf(5), reserialize(Suppliers.compose(
385 Functions.identity(), Suppliers.ofInstance(5))).get());
386 assertEquals(Integer.valueOf(5),
387 reserialize(Suppliers.memoize(Suppliers.ofInstance(5))).get());
388 assertEquals(Integer.valueOf(5),
389 reserialize(Suppliers.memoizeWithExpiration(
390 Suppliers.ofInstance(5), 30, TimeUnit.SECONDS)).get());
391 assertEquals(Integer.valueOf(5), reserialize(
392 Suppliers.synchronizedSupplier(Suppliers.ofInstance(5))).get());
393 }
394
395 @GwtIncompatible("reflection")
396 public void testSuppliersNullChecks() throws Exception {
397 new ClassSanityTester().forAllPublicStaticMethods(Suppliers.class)
398 .testNulls();
399 }
400
401 @GwtIncompatible("reflection")
402 public void testSuppliersSerializable() throws Exception {
403 new ClassSanityTester().forAllPublicStaticMethods(Suppliers.class)
404 .testSerializable();
405 }
406
407 public void testOfInstance_equals() {
408 new EqualsTester()
409 .addEqualityGroup(
410 Suppliers.ofInstance("foo"), Suppliers.ofInstance("foo"))
411 .addEqualityGroup(Suppliers.ofInstance("bar"))
412 .testEquals();
413 }
414
415 public void testCompose_equals() {
416 new EqualsTester()
417 .addEqualityGroup(
418 Suppliers.compose(Functions.constant(1), Suppliers.ofInstance("foo")),
419 Suppliers.compose(Functions.constant(1), Suppliers.ofInstance("foo")))
420 .addEqualityGroup(
421 Suppliers.compose(Functions.constant(2), Suppliers.ofInstance("foo")))
422 .addEqualityGroup(
423 Suppliers.compose(Functions.constant(1), Suppliers.ofInstance("bar")))
424 .testEquals();
425 }
426 }